home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9110.ZIP / DFLAT.101 < prev    next >
Text File  |  1991-09-10  |  29KB  |  915 lines

  1. _C PROGRAMMING COLUMN_
  2. by Al Stevens
  3.  
  4. [LISTING ONE]
  5.  
  6. /* --------------- lists.c -------------- */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <conio.h>
  12. #include <dos.h>
  13. #include "dflat.h"
  14.  
  15. struct LinkedList Focus = {NULLWND, NULLWND};
  16. struct LinkedList Built = {NULLWND, NULLWND};
  17.  
  18. /* --- set focus to the window beneath the one specified --- */
  19. void SetPrevFocus(WINDOW wnd)
  20. {
  21.     if (wnd != NULLWND && wnd == inFocus)    {
  22.         WINDOW wnd1 = wnd;
  23.         while (TRUE)    {
  24.             if ((wnd1 = PrevWindow(wnd1)) == NULLWND)
  25.                 wnd1 = Focus.LastWindow;
  26.             if (wnd1 == wnd)
  27.                 return;
  28.             if (wnd1 != NULLWND)
  29.                 break;
  30.         }
  31.         if (wnd1 != NULLWND)
  32.             SendMessage(wnd1, SETFOCUS, TRUE, 0);
  33.     }
  34. }
  35.  
  36. /* this function assumes that wnd is in the Focus linked list */
  37. static WINDOW SearchFocusNext(WINDOW wnd, WINDOW pwnd)
  38. {
  39.     WINDOW wnd1 = wnd;
  40.  
  41.     if (wnd != NULLWND)    {
  42.         while (TRUE)    {
  43.             if ((wnd1 = NextWindow(wnd1)) == NULLWND)
  44.                 wnd1 = Focus.FirstWindow;
  45.             if (wnd1 == wnd)
  46.                 return NULLWND;
  47.             if (wnd1 != NULLWND)
  48.                 if (pwnd == NULLWND || pwnd == GetParent(wnd1))
  49.                     break;
  50.         }
  51.     }
  52.     return wnd1;
  53. }
  54.  
  55. /* ----- set focus to the next sibling ----- */
  56. void SetNextFocus(WINDOW wnd)
  57. {
  58.     WINDOW wnd1;
  59.  
  60.     if (wnd != inFocus)
  61.         return;
  62.     if ((wnd1 = SearchFocusNext(wnd, GetParent(wnd)))==NULLWND)
  63.         wnd1 = SearchFocusNext(wnd, NULLWND);
  64.     if (wnd1 != NULLWND)
  65.         SendMessage(wnd1, SETFOCUS, TRUE, 0);
  66. }
  67.  
  68. /* ---- remove a window from the Built linked list ---- */
  69. void RemoveBuiltWindow(WINDOW wnd)
  70. {
  71.     if (wnd != NULLWND)    {
  72.         if (PrevWindowBuilt(wnd) != NULLWND)
  73.             NextWindowBuilt(PrevWindowBuilt(wnd)) =
  74.                 NextWindowBuilt(wnd);
  75.         if (NextWindowBuilt(wnd) != NULLWND)
  76.             PrevWindowBuilt(NextWindowBuilt(wnd)) =
  77.                 PrevWindowBuilt(wnd);
  78.         if (wnd == Built.FirstWindow)
  79.             Built.FirstWindow = NextWindowBuilt(wnd);
  80.         if (wnd == Built.LastWindow)
  81.             Built.LastWindow = PrevWindowBuilt(wnd);
  82.     }
  83. }
  84.  
  85. /* ---- remove a window from the Focus linked list ---- */
  86. void RemoveFocusWindow(WINDOW wnd)
  87. {
  88.     if (wnd != NULLWND)    {
  89.         if (PrevWindow(wnd) != NULLWND)
  90.             NextWindow(PrevWindow(wnd)) = NextWindow(wnd);
  91.         if (NextWindow(wnd) != NULLWND)
  92.             PrevWindow(NextWindow(wnd)) = PrevWindow(wnd);
  93.         if (wnd == Focus.FirstWindow)
  94.             Focus.FirstWindow = NextWindow(wnd);
  95.         if (wnd == Focus.LastWindow)
  96.             Focus.LastWindow = PrevWindow(wnd);
  97.     }
  98. }
  99.  
  100. /* ---- append a window to the Built linked list ---- */
  101. void AppendBuiltWindow(WINDOW wnd)
  102. {
  103.     if (wnd != NULLWND)    {
  104.         if (Built.FirstWindow == NULLWND)
  105.             Built.FirstWindow = wnd;
  106.         if (Built.LastWindow != NULLWND)
  107.             NextWindowBuilt(Built.LastWindow) = wnd;
  108.         PrevWindowBuilt(wnd) = Built.LastWindow;
  109.         NextWindowBuilt(wnd) = NULLWND;
  110.         Built.LastWindow = wnd;
  111.     }
  112. }
  113.  
  114. /* ---- append a window to the Focus linked list ---- */
  115. void AppendFocusWindow(WINDOW wnd)
  116. {
  117.     if (wnd != NULLWND)    {
  118.         if (Focus.FirstWindow == NULLWND)
  119.             Focus.FirstWindow = wnd;
  120.         if (Focus.LastWindow != NULLWND)
  121.             NextWindow(Focus.LastWindow) = wnd;
  122.         PrevWindow(wnd) = Focus.LastWindow;
  123.         NextWindow(wnd) = NULLWND;
  124.         Focus.LastWindow = wnd;
  125.     }
  126. }
  127.  
  128. /* -------- get the first child of a parent window ------- */
  129. WINDOW GetFirstChild(WINDOW wnd)
  130. {
  131.     WINDOW ThisWindow = Built.FirstWindow;
  132.     while (ThisWindow != NULLWND)    {
  133.         if (GetParent(ThisWindow) == wnd)
  134.             break;
  135.         ThisWindow = NextWindowBuilt(ThisWindow);
  136.     }
  137.     return ThisWindow;
  138. }
  139.  
  140. /* -------- get the next child of a parent window ------- */
  141. WINDOW GetNextChild(WINDOW wnd, WINDOW ThisWindow)
  142. {
  143.     if (ThisWindow != NULLWND)    {
  144.         do    {
  145.             if ((ThisWindow = NextWindowBuilt(ThisWindow)) !=
  146.                     NULLWND)
  147.                 if (GetParent(ThisWindow) == wnd)
  148.                     break;
  149.         }    while (ThisWindow != NULLWND);
  150.     }
  151.     return ThisWindow;
  152. }
  153.  
  154. /* -- get first child of parent window from the Focus list -- */
  155. WINDOW GetFirstFocusChild(WINDOW wnd)
  156. {
  157.     WINDOW ThisWindow = Focus.FirstWindow;
  158.     while (ThisWindow != NULLWND)    {
  159.         if (GetParent(ThisWindow) == wnd)
  160.             break;
  161.         ThisWindow = NextWindow(ThisWindow);
  162.     }
  163.     return ThisWindow;
  164. }
  165.  
  166. /* -- get next child of parent window from the Focus list -- */
  167. WINDOW GetNextFocusChild(WINDOW wnd, WINDOW ThisWindow)
  168. {
  169.     while (ThisWindow != NULLWND)    {
  170.         ThisWindow = NextWindow(ThisWindow);
  171.         if (ThisWindow != NULLWND)
  172.             if (GetParent(ThisWindow) == wnd)
  173.                 break;
  174.     }
  175.     return ThisWindow;
  176. }
  177.  
  178. /* -------- get the last child of a parent window ------- */
  179. WINDOW GetLastChild(WINDOW wnd)
  180. {
  181.     WINDOW ThisWindow = Built.LastWindow;
  182.     while (ThisWindow != NULLWND)    {
  183.         if (GetParent(ThisWindow) == wnd)
  184.             break;
  185.         ThisWindow = PrevWindowBuilt(ThisWindow);
  186.     }
  187.     return ThisWindow;
  188. }
  189.  
  190. /* ------- get the previous child of a parent window ------- */
  191. WINDOW GetPrevChild(WINDOW wnd, WINDOW ThisWindow)
  192. {
  193.     if (ThisWindow != NULLWND)    {
  194.         do    {
  195.             if ((ThisWindow = PrevWindowBuilt(ThisWindow)) !=
  196.                     NULLWND)
  197.                 if (GetParent(ThisWindow) == wnd)
  198.                     break;
  199.         }    while (ThisWindow != NULLWND);
  200.     }
  201.     return ThisWindow;
  202. }
  203.  
  204. /* --- bypass system windows when stepping through focus --- */
  205. void SkipSystemWindows(int Prev)
  206. {
  207.     int cl, ct = 0;
  208.     while ((cl = GetClass(inFocus)) == MENUBAR ||
  209.             cl == APPLICATION
  210. #ifdef INCLUDE_STATUSBAR
  211.                  || cl == STATUSBAR
  212. #endif
  213.                                 )    {
  214.         if (Prev)
  215.             SetPrevFocus(inFocus);
  216.         else 
  217.             SetNextFocus(inFocus);
  218.         if (++ct == 3)
  219.             break;
  220.     }
  221. }
  222.  
  223.  
  224. [LISTING TWO]
  225.  
  226. /* ------------- rect.c --------------- */
  227.  
  228. #include <dos.h>
  229. #include "dflat.h"
  230.  
  231.  /* -- Produce vector end points produced by overlap of two other vectors -- */
  232. static void subVector(int *v1, int *v2, int t1, int t2, int o1, int o2)
  233. {
  234.     *v1 = *v2 = -1;
  235.     if (within(o1, t1, t2))    {
  236.         *v1 = o1;
  237.         if (within(o2, t1, t2))
  238.             *v2 = o2;
  239.         else
  240.             *v2 = t2;
  241.     }
  242.     else if (within(o2, t1, t2))    {
  243.         *v2 = o2;
  244.         if (within(o1, t1, t2))
  245.             *v1 = o1;
  246.         else
  247.             *v1 = t1;
  248.     }
  249.     else if (within(t1, o1, o2))    {
  250.         *v1 = t1;
  251.         if (within(t2, o1, o2))
  252.             *v2 = t2;
  253.         else
  254.             *v2 = o2;
  255.     }
  256.     else if (within(t2, o1, o2))    {
  257.         *v2 = t2;
  258.         if (within(t1, o1, o2))
  259.             *v1 = t1;
  260.         else
  261.             *v1 = o1;
  262.     }
  263. }
  264.  
  265.  /* -- Return rectangle produced by the overlap of two other rectangles --- */
  266. RECT subRectangle(RECT r1, RECT r2)
  267. {
  268.     RECT r = {0,0,0,0};
  269.     subVector((int *) &RectLeft(r), (int *) &RectRight(r),
  270.         RectLeft(r1), RectRight(r1),
  271.         RectLeft(r2), RectRight(r2));
  272.     subVector((int *) &RectTop(r), (int *) &RectBottom(r),
  273.         RectTop(r1), RectBottom(r1),
  274.         RectTop(r2), RectBottom(r2));
  275.     if (RectRight(r) == -1 || RectTop(r) == -1)
  276.         RectRight(r) =
  277.         RectLeft(r) =
  278.         RectTop(r) =
  279.         RectBottom(r) = 0;
  280.     return r;
  281. }
  282.  
  283. /* ------- return the client rectangle of a window ------ */
  284. RECT ClientRect(void *wnd)
  285. {
  286.     RECT rc;
  287.  
  288.     RectLeft(rc) = GetClientLeft((WINDOW)wnd);
  289.     RectTop(rc) = GetClientTop((WINDOW)wnd);
  290.     RectRight(rc) = GetClientRight((WINDOW)wnd);
  291.     RectBottom(rc) = GetClientBottom((WINDOW)wnd);
  292.     return rc;
  293. }
  294.  
  295. /* ---- return the rectangle relative to its window's screen position ---- */
  296. RECT RelativeWindowRect(void *wnd, RECT rc)
  297. {
  298.     RectLeft(rc) -= GetLeft((WINDOW)wnd);
  299.     RectRight(rc) -= GetLeft((WINDOW)wnd);
  300.     RectTop(rc) -= GetTop((WINDOW)wnd);
  301.     RectBottom(rc) -= GetTop((WINDOW)wnd);
  302.     return rc;
  303. }
  304.  
  305. /* ----- clip a rectangle to the parents of the window ----- */
  306. RECT ClipRectangle(void *wnd, RECT rc)
  307. {
  308.     RECT sr;
  309.     RectLeft(sr) = RectTop(sr) = 0;
  310.     RectRight(sr) = SCREENWIDTH-1;
  311.     RectBottom(sr) = SCREENHEIGHT-1;
  312.     if (!TestAttribute((WINDOW)wnd, NOCLIP))
  313.         while ((wnd = GetParent((WINDOW)wnd)) != NULLWND)
  314.             rc = subRectangle(rc, ClientRect(wnd));
  315.     return subRectangle(rc, sr);
  316. }
  317.  
  318.  
  319.  
  320.  
  321. [LISTING THREE]
  322.  
  323. /* ----------- dflatmsg.h ------------ */
  324.  
  325. /* message foundation file
  326.  * make message changes here
  327.  * other source files will adapt
  328.  */
  329.  
  330. /* -------------- process communication messages ----------- */
  331. DFlatMsg(START)              /* start message processing     */
  332. DFlatMsg(STOP)               /* stop message processing      */
  333. DFlatMsg(COMMAND)            /* send a command to a window   */
  334. /* -------------- window management messages --------------- */
  335. DFlatMsg(CREATE_WINDOW)      /* create a window              */
  336. DFlatMsg(SHOW_WINDOW)        /* show a window                */
  337. DFlatMsg(HIDE_WINDOW)        /* hide a window                */
  338. DFlatMsg(CLOSE_WINDOW)       /* delete a window              */
  339. DFlatMsg(SETFOCUS)           /* set and clear the focus      */
  340. DFlatMsg(PAINT)              /* paint the window's data space*/
  341. DFlatMsg(BORDER)             /* paint the window's border    */
  342. DFlatMsg(TITLE)              /* display the window's title   */
  343. DFlatMsg(MOVE)               /* move the window              */
  344. DFlatMsg(SIZE)               /* change the window's size     */
  345. DFlatMsg(MAXIMIZE)           /* maximize the window          */
  346. DFlatMsg(MINIMIZE)           /* minimize the window          */
  347. DFlatMsg(RESTORE)            /* restore the window           */
  348. DFlatMsg(INSIDE_WINDOW)      /* test x/y inside a window     */
  349. /* ---------------- clock messages ------------------------- */
  350. DFlatMsg(CLOCKTICK)          /* the clock ticked             */
  351. DFlatMsg(CAPTURE_CLOCK)      /* capture clock into a window  */
  352. DFlatMsg(RELEASE_CLOCK)      /* release clock to the system  */
  353. /* -------------- keyboard and screen messages ------------- */
  354. DFlatMsg(KEYBOARD)           /* key was pressed              */
  355. DFlatMsg(CAPTURE_KEYBOARD) /* capture keyboard into a window */
  356. DFlatMsg(RELEASE_KEYBOARD)   /* release keyboard to system   */
  357. DFlatMsg(KEYBOARD_CURSOR)    /* position the keyboard cursor */
  358. DFlatMsg(CURRENT_KEYBOARD_CURSOR) /*read the cursor position */
  359. DFlatMsg(HIDE_CURSOR)        /* hide the keyboard cursor     */
  360. DFlatMsg(SHOW_CURSOR)        /* display the keyboard cursor  */
  361. DFlatMsg(SAVE_CURSOR)      /* save the cursor's configuration*/
  362. DFlatMsg(RESTORE_CURSOR)     /* restore the saved cursor     */
  363. DFlatMsg(SHIFT_CHANGED)      /* the shift status changed     */
  364. DFlatMsg(WAITKEYBOARD)     /* waits for a key to be released */
  365. /* ---------------- mouse messages ------------------------- */
  366. DFlatMsg(MOUSE_INSTALLED)    /* test for mouse installed     */
  367. DFlatMsg(RIGHT_BUTTON)       /* right button pressed         */
  368. DFlatMsg(LEFT_BUTTON)        /* left button pressed          */
  369. DFlatMsg(DOUBLE_CLICK)       /* left button double-clicked   */
  370. DFlatMsg(MOUSE_MOVED)        /* mouse changed position       */
  371. DFlatMsg(BUTTON_RELEASED)    /* mouse button released        */
  372. DFlatMsg(CURRENT_MOUSE_CURSOR)/* get mouse position          */
  373. DFlatMsg(MOUSE_CURSOR)       /* set mouse position           */
  374. DFlatMsg(SHOW_MOUSE)         /* make mouse cursor visible    */
  375. DFlatMsg(HIDE_MOUSE)         /* hide mouse cursor            */
  376. DFlatMsg(WAITMOUSE)          /* wait until button released   */
  377. DFlatMsg(TESTMOUSE)          /* test any mouse button pressed*/
  378. DFlatMsg(CAPTURE_MOUSE)      /* capture mouse into a window  */
  379. DFlatMsg(RELEASE_MOUSE)      /* release the mouse to system  */
  380. /* ---------------- text box messages ---------------------- */
  381. DFlatMsg(ADDTEXT)            /* add text to the text box     */
  382. DFlatMsg(CLEARTEXT)          /* clear the edit box           */
  383. DFlatMsg(SETTEXT)            /* set address of text buffer   */
  384. DFlatMsg(SCROLL)             /* vertical scroll of text box  */
  385. DFlatMsg(HORIZSCROLL)        /* horizontal scroll of text box*/
  386. /* ---------------- edit box messages ---------------------- */
  387. DFlatMsg(EB_GETTEXT)         /* get text from an edit box    */
  388. DFlatMsg(EB_PUTTEXT)         /* put text into an edit box    */
  389. /* ---------------- menubar messages ----------------------- */
  390. DFlatMsg(BUILDMENU)          /* build the menu display       */
  391. DFlatMsg(SELECTION)          /* menubar selection            */
  392. /* ---------------- popdown messages ----------------------- */
  393. DFlatMsg(BUILD_SELECTIONS)   /* build the menu display       */
  394. DFlatMsg(CLOSE_POPDOWN)    /* tell parent popdown is closing */
  395. /* ---------------- list box messages ---------------------- */
  396. DFlatMsg(LB_SELECTION)       /* sent to parent on selection  */
  397. DFlatMsg(LB_CHOOSE)          /* sent when user chooses       */
  398. DFlatMsg(LB_CURRENTSELECTION)/* return the current selection */
  399. DFlatMsg(LB_GETTEXT)         /* return the text of selection */
  400. DFlatMsg(LB_SETSELECTION)    /* sets the listbox selection   */
  401. /* ---------------- dialog box messages -------------------- */
  402. DFlatMsg(INITIATE_DIALOG)    /* begin a dialog               */
  403. DFlatMsg(ENTERFOCUS)         /* tell DB control got focus    */
  404. DFlatMsg(LEAVEFOCUS)         /* tell DB control lost focus   */
  405. DFlatMsg(ENDDIALOG)          /* end a dialog                 */
  406. /* ---------------- help box messages ---------------------- */
  407. DFlatMsg(DISPLAY_HELP)
  408. /* --------------- application window messages ------------- */
  409. DFlatMsg(ADDSTATUS)
  410.  
  411.  
  412.  
  413. [LISTING FOUR]
  414.  
  415. /* ---------------- commands.h ----------------- */
  416.  
  417. /* Command values sent as the first parameter
  418.  * in the COMMAND message
  419.  * Add application-specific commands to this enum
  420.  */
  421.  
  422. #ifndef COMMANDS_H
  423. #define COMMANDS_H
  424.  
  425. enum commands {
  426.     /* --------------- File menu ---------------- */
  427.     ID_OPEN,
  428.     ID_NEW,
  429.     ID_SAVE,
  430.     ID_SAVEAS,
  431.     ID_DELETEFILE,
  432.     ID_PRINT,
  433.     ID_DOS,
  434.     ID_EXIT,
  435.     /* --------------- Edit menu ---------------- */
  436.     ID_UNDO,
  437.     ID_CUT,
  438.     ID_COPY,
  439.     ID_PASTE,
  440.     ID_PARAGRAPH,
  441.     ID_CLEAR,
  442.     ID_DELETETEXT,
  443.     /* --------------- Search Menu -------------- */
  444.     ID_SEARCH,
  445.     ID_REPLACE,
  446.     ID_SEARCHNEXT,
  447.     /* -------------- Options menu -------------- */
  448.     ID_INSERT,
  449.     ID_WRAP,
  450.     ID_LOG,
  451.     ID_TABS,
  452.     ID_DISPLAY,
  453.     ID_SAVEOPTIONS,
  454.     /* --------------- Window menu -------------- */
  455.     ID_WINDOW,
  456.     ID_CLOSEALL,
  457.     /* --------------- Help menu ---------------- */
  458.     ID_HELPHELP,
  459.     ID_EXTHELP,
  460.     ID_KEYSHELP,
  461.     ID_HELPINDEX,
  462.     ID_ABOUT,
  463.     ID_LOADHELP,
  464.     /* --------------- System menu -------------- */
  465.     ID_SYSRESTORE,
  466.     ID_SYSMOVE,
  467.     ID_SYSSIZE,
  468.     ID_SYSMINIMIZE,
  469.     ID_SYSMAXIMIZE,
  470.     ID_SYSCLOSE,
  471.     /* ---- FileOpen and SaveAs dialog boxes ---- */
  472.     ID_FILENAME,
  473.     ID_FILES,
  474.     ID_DRIVE,
  475.     ID_PATH,
  476.     /* ----- Search and Replace dialog boxes ---- */
  477.     ID_SEARCHFOR,
  478.     ID_REPLACEWITH,
  479.     ID_MATCHCASE,
  480.     ID_REPLACEALL,
  481.     /* ----------- Windows dialog box ----------- */
  482.     ID_WINDOWLIST,
  483.     /* --------- generic command buttons -------- */
  484.     ID_OK,
  485.     ID_CANCEL,
  486.     ID_HELP,
  487.     /* -------------- TabStops menu ------------- */
  488.     ID_TAB2,
  489.     ID_TAB4,
  490.     ID_TAB6,
  491.     ID_TAB8,
  492.     /* ------------ Display dialog box ---------- */
  493.     ID_BORDER,
  494.     ID_TITLE,
  495.     ID_STATUSBAR,
  496.     ID_TEXTURE,
  497.     ID_COLOR,
  498.     ID_MONO,
  499.     ID_REVERSE,
  500.     ID_25LINES,
  501.     ID_43LINES,
  502.     ID_50LINES,
  503.     /* ------------- Log dialog box ------------- */
  504.     ID_LOGLIST,
  505.     ID_LOGGING,
  506.     /* ------------ HelpBox dialog box ---------- */
  507.     ID_HELPTEXT,
  508.     ID_BACK,
  509.     ID_PREV,
  510.     ID_NEXT
  511. };
  512.  
  513. #endif
  514.  
  515.  
  516.  
  517.  
  518. [LISTING FIVE]
  519.  
  520. /* --------------- memopad.c ----------- */
  521.  
  522. #include <stdio.h>
  523. #include <stdlib.h>
  524. #include <string.h>
  525. #include <sys\types.h>
  526. #include <sys\stat.h>
  527. #include <dos.h>
  528. #ifndef MSC
  529. #include <dir.h>
  530. #endif
  531. #include "dflat.h"
  532.  
  533. static char Untitled[] = "Untitled";
  534. static int wndpos = 0;
  535.  
  536. static int MemoPadProc(WINDOW, MESSAGE, PARAM, PARAM);
  537. static void NewFile(WINDOW);
  538. static void SelectFile(WINDOW);
  539. static void PadWindow(WINDOW, char *);
  540. static void OpenPadWindow(WINDOW, char *);
  541. static void LoadFile(WINDOW, int);
  542. static void PrintPad(WINDOW);
  543. static void SaveFile(WINDOW, int);
  544. static void DeleteFile(WINDOW);
  545. static int EditorProc(WINDOW, MESSAGE, PARAM, PARAM);
  546. static char *NameComponent(char *);
  547. char **Argv;
  548.  
  549. void main(int argc, char *argv[])
  550. {
  551.     WINDOW wnd;
  552.     init_messages();
  553.     Argv = argv;
  554.     wnd = CreateWindow(APPLICATION,
  555.                         "D-Flat MemoPad " VERSION,
  556.                         0, 0, -1, -1,
  557.                         &MainMenu,
  558.                         NULL,
  559.                         MemoPadProc,
  560.                         MOVEABLE  |
  561.                         SIZEABLE  |
  562.                         HASBORDER |
  563.                         HASSTATUSBAR
  564.                         );
  565.  
  566.     SendMessage(wnd, SETFOCUS, TRUE, 0);
  567.     while (argc > 1)    {
  568.         PadWindow(wnd, argv[1]);
  569.         --argc;
  570.         argv++;
  571.     }
  572.     while (dispatch_message())
  573.         ;
  574. }
  575. /* ------ open text files and put them into editboxes ----- */
  576. static void PadWindow(WINDOW wnd, char *FileName)
  577. {
  578.     int ax, criterr = 1;
  579.     struct ffblk ff;
  580.     char path[64];
  581.     char *cp;
  582.  
  583.     CreatePath(path, FileName, FALSE, FALSE);
  584.     cp = path+strlen(path);
  585.     CreatePath(path, FileName, TRUE, FALSE);
  586.     while (criterr == 1)    {
  587.         ax = findfirst(path, &ff, 0);
  588.         criterr = TestCriticalError();
  589.     }
  590.     while (ax == 0 && !criterr)    {
  591.         strcpy(cp, ff.ff_name);
  592.         OpenPadWindow(wnd, path);
  593.         ax = findnext(&ff);
  594.     }
  595. }
  596. /* ----- window processing module for the memopad application window ----- */
  597. static int MemoPadProc(WINDOW wnd,MESSAGE msg,PARAM p1,PARAM p2)
  598. {
  599.     switch (msg)    {
  600.         case COMMAND:
  601.             switch ((int)p1)    {
  602.                 case ID_NEW:
  603.                     NewFile(wnd);
  604.                     return TRUE;
  605.                 case ID_OPEN:
  606.                     SelectFile(wnd);
  607.                     return TRUE;
  608.                 case ID_SAVE:
  609.                     SaveFile(inFocus, FALSE);
  610.                     return TRUE;
  611.                 case ID_SAVEAS:
  612.                     SaveFile(inFocus, TRUE);
  613.                     return TRUE;
  614.                 case ID_DELETEFILE:
  615.                     DeleteFile(inFocus);
  616.                     return TRUE;
  617.                 case ID_PRINT:
  618.                     PrintPad(inFocus);
  619.                     return TRUE;
  620.                 case ID_ABOUT:
  621.                     MessageBox(
  622.                          "About D-Flat and the MemoPad",
  623.                         "   ┌───────────────────────┐\n"
  624.                         "   │    ▄▄▄   ▄▄▄     ▄    │\n"
  625.                         "   │    █  █  █  █    █    │\n"
  626.                         "   │    █  █  █  █    █    │\n"
  627.                         "   │    █  █  █  █ █  █    │\n"
  628.                         "   │    ▀▀▀   ▀▀▀   ▀▀     │\n"
  629.                         "   └───────────────────────┘\n"
  630.                         "D-Flat implements the SAA/CUA\n"
  631.                         "interface in a public domain\n"
  632.                         "C language library originally\n"
  633.                         "published in Dr. Dobb's Journal\n"
  634.                         "    ------------------------ \n"
  635.                         "MemoPad is a multiple document\n"
  636.                         "editor that demonstrates D-Flat");
  637.                     MessageBox(
  638.                         "D-Flat Testers and Friends",
  639.             "Jeff Ratcliff, David Peoples, Kevin Slater,\n"
  640.             "Naor Toledo Pinto, Jeff Hahn, Jim Drash,\n"
  641.             "Art Stricek, John Ebert, George Dinwiddie,\n"
  642.             "Damaian Thorne, Wes Peterson, Thomas Ewald,\n"
  643.             "Mitch Miller, Ray Waters, Jim Drash, Eric\n"
  644.             "Silver, Russ Nelson, Elliott Jackson, Warren\n"
  645.             "Master, H.J. Davey, Jim Kyle, Jim Morris,\n"
  646.             "Andrew Terry, Michel Berube, Bruce Edmondson,\n"
  647.             "Peter Baenziger, Phil Roberge, Willie Hutton,\n"
  648.             "Randy Bradley, Tim Gentry, Lee Humphrey,\n"
  649.             "Larry Troxler, Robert DiFalco, Carl Huff,\n"
  650.             "Vince Rice, Michael Kaufman, Donald Cumming,\n"
  651.             "Ross Wheeler, Lou DiNardo, Keith London, Frank\n"
  652.             "Burleigh, Jason Ward, Skip Key, Sam Gentile,\n"
  653.             "Dana P'Simer, Ken North");
  654.                     return TRUE;
  655.                 default:
  656.                     break;
  657.             }
  658.             break;
  659.         default:
  660.             break;
  661.     }
  662.     return DefaultWndProc(wnd, msg, p1, p2);
  663. }
  664. /* --- The New command. Open an empty editor window --- */
  665. static void NewFile(WINDOW wnd)
  666. {
  667.     OpenPadWindow(wnd, Untitled);
  668. }
  669. /* --- The Open... command. Select a file  --- */
  670. static void SelectFile(WINDOW wnd)
  671. {
  672.     char FileName[64];
  673.     if (OpenFileDialogBox("*.PAD", FileName))    {
  674.         /* --- see if the document is already in a window --- */
  675.         WINDOW wnd1 = GetFirstChild(wnd);
  676.         while (wnd1 != NULLWND)    {
  677.             if (stricmp(FileName, wnd1->extension) == 0)    {
  678.                 SendMessage(wnd1, SETFOCUS, TRUE, 0);
  679.                 SendMessage(wnd1, RESTORE, 0, 0);
  680.                 return;
  681.             }
  682.             wnd1 = GetNextChild(wnd, wnd1);
  683.         }
  684.         OpenPadWindow(wnd, FileName);
  685.     }
  686. }
  687. /* --- open a document window and load a file --- */
  688. static void OpenPadWindow(WINDOW wnd, char *FileName)
  689. {
  690.     static WINDOW wnd1 = NULLWND;
  691.     struct stat sb;
  692.     char *Fname = FileName;
  693.     char *ermsg;
  694.     if (strcmp(FileName, Untitled))    {
  695.         if (stat(FileName, &sb))    {
  696.             if ((ermsg = malloc(strlen(FileName)+20)) != NULL) {
  697.                 strcpy(ermsg, "No such file as\n");
  698.                 strcat(ermsg, FileName);
  699.                 ErrorMessage(ermsg);
  700.                 free(ermsg);
  701.             }
  702.             return;
  703.         }
  704.         Fname = NameComponent(FileName);
  705.     }
  706.     wndpos += 2;
  707.     if (wndpos == 20)
  708.         wndpos = 2;
  709.     wnd1 = CreateWindow(EDITBOX,
  710.                 Fname,
  711.                 (wndpos-1)*2, wndpos, 10, 40,
  712.                 NULL, wnd, EditorProc,
  713.                 SHADOW     |
  714.                 MINMAXBOX  |
  715.                 CONTROLBOX |
  716.                 VSCROLLBAR |
  717.                 HSCROLLBAR |
  718.                 MOVEABLE   |
  719.                 HASBORDER  |
  720.                 SIZEABLE   |
  721.                 MULTILINE
  722.     );
  723.     if (strcmp(FileName, Untitled))    {
  724.         if ((wnd1->extension =
  725.                 malloc(strlen(FileName)+1)) != NULL)    {
  726.             strcpy(wnd1->extension, FileName);
  727.             LoadFile(wnd1, (int) sb.st_size);
  728.         }
  729.     }
  730.     SendMessage(wnd1, SETFOCUS, TRUE, 0);
  731. }
  732. /* --- Load the notepad file into the editor text buffer --- */
  733. static void LoadFile(WINDOW wnd, int tLen)
  734. {
  735.     char *Buf;
  736.     FILE *fp;
  737.  
  738.     if ((Buf = malloc(tLen+1)) != NULL)    {
  739.         if ((fp = fopen(wnd->extension, "rt")) != NULL)    {
  740.             memset (Buf, 0, tLen+1);
  741.             fread(Buf, tLen, 1, fp);
  742.             SendMessage(wnd, SETTEXT, (PARAM) Buf, 0);
  743.             fclose(fp);
  744.         }
  745.         free(Buf);
  746.     }
  747. }
  748. /* --- print the current notepad --- */
  749. static void PrintPad(WINDOW wnd)
  750. {
  751.     unsigned char *text;
  752.  
  753.     /* ---------- print the file name ---------- */
  754.     fputs("\r\n", stdprn);
  755.     fputs(GetTitle(wnd), stdprn);
  756.     fputs(":\r\n\n", stdprn);
  757.  
  758.     /* ---- get the address of the editor text ----- */
  759.     text = GetText(wnd);
  760.  
  761.     /* ------- print the notepad text --------- */
  762.     while (*text)    {
  763.         if (*text == '\n')
  764.             fputc('\r', stdprn);
  765.         fputc(*text++, stdprn);
  766.     }
  767.  
  768.     /* ------- follow with a form feed? --------- */
  769.     if (YesNoBox("Form Feed?"))
  770.         fputc('\f', stdprn);
  771. }
  772. /* ---------- save a file to disk ------------ */
  773. static void SaveFile(WINDOW wnd, int Saveas)
  774. {
  775.     FILE *fp;
  776.     if (wnd->extension == NULL || Saveas)    {
  777.         char FileName[64];
  778.         if (SaveAsDialogBox(FileName))    {
  779.             if (wnd->extension != NULL)
  780.                 free(wnd->extension);
  781.             if ((wnd->extension =
  782.                     malloc(strlen(FileName)+1)) != NULL)    {
  783.                 strcpy(wnd->extension, FileName);
  784.                 AddTitle(wnd, NameComponent(FileName));
  785.                 SendMessage(wnd, BORDER, 0, 0);
  786.             }
  787.         }
  788.         else
  789.             return;
  790.     }
  791.     if (wnd->extension != NULL)    {
  792.         WINDOW mwnd = MomentaryMessage("Saving the file");
  793.         if ((fp = fopen(wnd->extension, "wt")) != NULL)    {
  794.             fwrite(GetText(wnd), strlen(GetText(wnd)), 1, fp);
  795.             fclose(fp);
  796.             wnd->TextChanged = FALSE;
  797.         }
  798.         SendMessage(mwnd, CLOSE_WINDOW, 0, 0);
  799.     }
  800. }
  801. /* -------- delete a file ------------ */
  802. static void DeleteFile(WINDOW wnd)
  803. {
  804.     if (wnd->extension != NULL)    {
  805.         if (strcmp(wnd->extension, Untitled))    {
  806.             char *fn = NameComponent(wnd->extension);
  807.             if (fn != NULL)    {
  808.                 char msg[30];
  809.                 sprintf(msg, "Delete %s?", fn);
  810.                 if (YesNoBox(msg))    {
  811.                     unlink(wnd->extension);
  812.                     SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  813.                 }
  814.             }
  815.         }
  816.     }
  817. }
  818. /* ------ display the row and column in the statusbar ------ */
  819. static void ShowPosition(WINDOW wnd)
  820. {
  821.     char status[30];
  822.     sprintf(status, "Line:%4d  Column: %2d",
  823.         wnd->CurrLine, wnd->CurrCol);
  824.     SendMessage(GetParent(wnd), ADDSTATUS, (PARAM) status, 0);
  825. }
  826. /* ----- window processing module for the editboxes ----- */
  827. static int EditorProc(WINDOW wnd,MESSAGE msg,PARAM p1,PARAM p2)
  828. {
  829.     int rtn;
  830.     switch (msg)    {
  831.         case SETFOCUS:
  832.             rtn = DefaultWndProc(wnd, msg, p1, p2);
  833.             if ((int)p1 == FALSE)
  834.                 SendMessage(GetParent(wnd), ADDSTATUS, 0, 0);
  835.             else 
  836.                 ShowPosition(wnd);
  837.             return rtn;
  838.         case KEYBOARD_CURSOR:
  839.             rtn = DefaultWndProc(wnd, msg, p1, p2);
  840.             ShowPosition(wnd);
  841.             return rtn;
  842.         case COMMAND:
  843.             if ((int) p1 == ID_HELP)    {
  844.                 DisplayHelp(wnd, "MEMOPADDOC");
  845.                 return TRUE;
  846.             }
  847.             break;
  848.         case CLOSE_WINDOW:
  849.             if (wnd->TextChanged)    {
  850.                 char *cp = malloc(25+strlen(GetTitle(wnd)));
  851.                 SendMessage(wnd, SETFOCUS, TRUE, 0);
  852.                 if (cp != NULL)    {
  853.                     strcpy(cp, GetTitle(wnd));
  854.                     strcat(cp, "\nText changed. Save it?");
  855.                     if (YesNoBox(cp))
  856.                         SendMessage(GetParent(wnd),
  857.                             COMMAND, ID_SAVE, 0);
  858.                     free(cp);
  859.                 }
  860.             }
  861.             wndpos = 0;
  862.             if (wnd->extension != NULL)    {
  863.                 free(wnd->extension);
  864.                 wnd->extension = NULL;
  865.             }
  866.             break;
  867.         default:
  868.             break;
  869.     }
  870.     return DefaultWndProc(wnd, msg, p1, p2);
  871. }
  872. /* -- point to the name component of a file specification -- */
  873. static char *NameComponent(char *FileName)
  874. {
  875.     char *Fname;
  876.     if ((Fname = strrchr(FileName, '\\')) == NULL)
  877.         if ((Fname = strrchr(FileName, ':')) == NULL)
  878.             Fname = FileName-1;
  879.     return Fname + 1;
  880. }
  881.  
  882.  
  883.  
  884.  
  885. Examplσ 1:
  886.  
  887.  WINDOW cwnd = GetFirstChild(pwnd);
  888.  while (cwnd != NULLWND)   {
  889.      /* -- process the child window -- */
  890.      cwnd = GetNextChild(pwnd, cwnd);
  891. è }
  892.  
  893.  
  894. Examplσ 2:
  895.  
  896.  
  897.  typedef enum messages {
  898.      #undef DFlatMsg
  899.      #define DFlatMsg(m) m,
  900.      #include "dflatmsg.h"
  901.      MESSAGECOUNT
  902.  } MESSAGE;
  903.  
  904.  
  905.  
  906.  
  907. Examplσ 3
  908.  
  909.  static char *message[] = {
  910.      #undef DFlatMsg
  911.      #define DFlatMsg(m) " " #m,
  912.      #include "dflatmsg.h"
  913.      NULL
  914. è };
  915.